package sg.edu.nus.iss.jass.datastore;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;

import sg.edu.nus.iss.jass.datastore.exception.DataStoreException;
import sg.edu.nus.iss.jass.datastore.impl.DataMapper;
import sg.edu.nus.iss.jass.datastore.impl.PropertiesStorage;
import sg.edu.nus.iss.jass.datastore.impl.TSupportFileDataStore;

/**
 * <p>This class is the root class of all DAO classes.</p>
 * 
 * This class provides generalized features of data operations including
 * create/read/update/delete.
 * </br>
 * This class is the wrapper of IDataStore {@link IDataStore}
 * 
 * @author Wang DaYong
 *
 */
public abstract class BaseDAO {

	private static final String PATH_SEP = System.getProperty("file.separator");

	private static String absFolderName = "data";

	private static String storeFolder;

	private static IDataStore dataStore;

	static {
		try {
			storeFolder = (new File(".").getCanonicalPath().concat(PATH_SEP).concat(absFolderName).concat(PATH_SEP));
			dataStore = new TSupportFileDataStore(new PropertiesStorage(storeFolder, new DataMapper()));
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	/**
	 * Wrapper of {@link IDataStore#loadObjectByID}
	 */
	@SuppressWarnings("unchecked")
	public <T extends BaseDTO> T selectById(Type type, String id) throws DataStoreException {

		return (T)dataStore.loadObjectByID(type, id);
	}

	/**
	 * Wrapper of {@link IDataStore#loadObjectsByType}
	 */
	protected <T extends BaseDTO> List<T> selectAll(Type type) throws DataStoreException {

		return dataStore.loadObjectsByType(type);
	}

	/**
	 * Wrapper of {@link IDataStore#loadObjectsByIDs}
	 */
	protected <T extends BaseDTO> List<T> selectByIds(Type type, String... ids) throws DataStoreException {

		return dataStore.loadObjectsByIDs(type, ids);
	}

	/**
	 * Wrapper of {@link IDataStore#loadObjectsBySelector}
	 */
	protected <T extends BaseDTO> List<T> select(Type type, ISelector selector) throws DataStoreException {

		return dataStore.loadObjectsBySelector(type, selector);
	}

	/**
	 * Wrapper of {@link IDataStore#saveObject}
	 */
	protected <T extends BaseDTO> void save(T object) throws DataStoreException {

		dataStore.saveObject(object);

	}

	/**
	 * Wrapper of {@link IDataStore#saveObjects}
	 */
	protected <T extends BaseDTO> void saveObjects(List<T> list) throws DataStoreException {

		dataStore.saveObjects(list);

	}

	/**
	 * Wrapper of {@link IDataStore#deleteObjectByID}
	 */
	protected <T extends BaseDTO> void deleteByID(Type type, String id) throws DataStoreException {

		dataStore.deleteObjectByID(type, id);

	}

	/**
	 * Wrapper of {@link IDataStore#deleteObjects}
	 */
	protected <T extends BaseDTO> void deleteObjects(List<T> list) throws DataStoreException {

		dataStore.deleteObjects(list);
	}


	/**
	 * Wrapper of {@link IDataStore#getTransaction}
	 */
	public Transaction getTransaction() throws DataStoreException {

		return dataStore.getTransaction();
	}
	
	/**
	 * Only for testing
	 * @param path
	 */
	@Deprecated
	public void setTestFolder(String path){
		try {
			storeFolder = (new File(".").getCanonicalPath().concat(PATH_SEP).concat(path).concat(PATH_SEP));
			dataStore = new TSupportFileDataStore(new PropertiesStorage(storeFolder, new DataMapper()));
		} catch (IOException e) {
			System.err.println(e);
		}
	}
	
	/**
	 * Clear all cache for testing use only
	 */
	@Deprecated
	public void clearCache(){
		((TSupportFileDataStore)dataStore).clearCache();
	}

}
